package com.christina.engine.processing.impl;

import com.christina.engine.context.ContextManager;
import com.christina.engine.context.model.ConversationContext;
import com.christina.engine.context.model.UserContext;
import com.christina.engine.processing.AbstractRequestProcessor;
import com.christina.engine.processing.model.ProcessingContext;
import com.christina.engine.processing.model.ProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 上下文处理器
 * 负责构建和管理处理上下文，获取用户上下文和对话上下文
 */
@Component
public class ContextProcessor extends AbstractRequestProcessor {
    
    private static final String PROCESSOR_NAME = "ContextProcessor";
    private static final int PROCESSOR_ORDER = 200; // 在验证处理器之后执行
    
    private final ContextManager contextManager;
    
    @Autowired
    public ContextProcessor(ContextManager contextManager) {
        super(PROCESSOR_NAME, PROCESSOR_ORDER);
        this.contextManager = contextManager;
    }
    
    @Override
    protected ProcessingResult doProcess(ProcessingContext context) {
        logger.debug("Starting context processing for requestId: {}", context.getRequestId());
        
        try {
            // 获取用户上下文
            UserContext userContext = getUserContext(context);
            boolean usedDefaultUserContext = false;
            String contextError = null;
            if (userContext != null) {
                context.setUserContext(userContext);
                logger.debug("User context loaded for userId: {}", context.getUserId());
            } else {
                logger.warn("Failed to load user context for userId: {}", context.getUserId());
                // 创建默认用户上下文
                userContext = createDefaultUserContext(context.getUserId());
                context.setUserContext(userContext);
                usedDefaultUserContext = true;
                contextError = "使用默认用户上下文，原上下文加载失败";
            }
            
            // 获取对话上下文
            ConversationContext conversationContext = getConversationContext(context);
            boolean usedDefaultConversationContext = false;
            if (conversationContext != null) {
                context.setConversationContext(conversationContext);
                logger.debug("Conversation context loaded for sessionId: {}", context.getSessionId());
            } else {
                logger.warn("Failed to load conversation context for sessionId: {}", context.getSessionId());
                // 创建默认对话上下文
                conversationContext = createDefaultConversationContext(context.getSessionId());
                context.setConversationContext(conversationContext);
                usedDefaultConversationContext = true;
                if (contextError == null) {
                    contextError = "使用默认对话上下文，原上下文加载失败";
                } else {
                    contextError += "; 使用默认对话上下文，原上下文加载失败";
                }
            }
            
            // 合并上下文信息
            Object mergedContext = mergeContexts(userContext, conversationContext);
            if (mergedContext != null) {
                context.setProcessingData("mergedContext", mergedContext);
            } else {
                logger.warn("Merged context is null, skipping setProcessingData");
            }
            
            // 更新上下文缓存状态
            updateContextCacheStatus(context, userContext, conversationContext);
            
            // 记录上下文处理状态
            String contextStatus = (usedDefaultUserContext || usedDefaultConversationContext) ? "DEFAULT" : "LOADED";
            context.setProcessingData("contextStatus", contextStatus);
            context.setProcessingData("contextLoadTimestamp", System.currentTimeMillis());
            
            logger.debug("Context processing completed for requestId: {}", context.getRequestId());
            
            ProcessingResult.Builder resultBuilder = ProcessingResult.builder()
                    .success(true)
                    .shouldContinue(true)
                    .processorName(PROCESSOR_NAME)
                    .resultData("contextStatus", contextStatus)
                    .resultData("userContextLoaded", userContext != null)
                    .resultData("conversationContextLoaded", conversationContext != null);
            
            if (contextError != null) {
                resultBuilder.resultData("contextError", contextError);
            }
            
            return resultBuilder.build();
                    
        } catch (Exception e) {
            logger.error("Error during context processing for requestId: {}", context.getRequestId(), e);
            
            // 记录上下文处理失败
            context.setProcessingData("contextStatus", "FAILED");
            context.setProcessingData("contextError", e.getMessage());
            
            logger.debug("doProcess caught exception: {}, rethrowing", e.getMessage());
            
            throw e;
        }
    }
    
    /**
     * 获取用户上下文
     */
    private UserContext getUserContext(ProcessingContext context) {
        try {
            Long userId = context.getUserId();
            if (userId == null) {
                logger.warn("User ID is null, cannot load user context");
                return null;
            }
            
            UserContext userContext = contextManager.getUserContext(userId);
            
            // 如果用户上下文不存在，尝试创建新的
            if (userContext == null) {
                logger.info("User context not found for userId: {}, creating new context", userId);
                userContext = createDefaultUserContext(userId);
                
                // 保存新创建的用户上下文
                contextManager.updateUserContext(userId, userContext);
            }
            
            return userContext;
            
        } catch (Exception e) {
            logger.error("Error loading user context for userId: {}", context.getUserId(), e);
            logger.warn("Failed to load user context, will use default context");
            return null;
        }
    }
    
    /**
     * 获取对话上下文
     */
    private ConversationContext getConversationContext(ProcessingContext context) {
        try {
            String sessionId = context.getSessionId();
            if (sessionId == null || sessionId.trim().isEmpty()) {
                logger.warn("Session ID is null or empty, cannot load conversation context");
                return null;
            }
            
            ConversationContext conversationContext = contextManager.getConversationContext(sessionId);
            
            // 如果对话上下文不存在，尝试创建新的
            if (conversationContext == null) {
                logger.info("Conversation context not found for sessionId: {}, creating new context", sessionId);
                conversationContext = createDefaultConversationContext(sessionId);
                
                // 保存新创建的对话上下文
                contextManager.updateConversationContext(sessionId, conversationContext);
            }
            
            return conversationContext;
            
        } catch (Exception e) {
            logger.error("Error loading conversation context for sessionId: {}", context.getSessionId(), e);
            logger.warn("Failed to load conversation context, will use default context");
            return null;
        }
    }
    
    /**
     * 创建默认用户上下文
     */
    private UserContext createDefaultUserContext(Long userId) {
        return UserContext.builder()
                .userId(userId)
                .preferences(UserContext.UserPreferences.builder()
                        .customPreferences(new HashMap<>())
                        .build())
                .profile(UserContext.UserProfile.builder()
                        .language("zh-CN")
                        .build())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
    }
    
    /**
     * 创建默认对话上下文
     */
    private ConversationContext createDefaultConversationContext(String sessionId) {
        return ConversationContext.builder()
                .sessionId(sessionId)
                .conversationHistory(new ArrayList<>())
                .currentTopic("")
                .state(ConversationContext.ConversationState.ACTIVE)
                .sessionVariables(new HashMap<>())
                .startTime(LocalDateTime.now())
                .lastActiveTime(LocalDateTime.now())
                .expireTime(LocalDateTime.now().plusHours(24))
                .build();
    }
    
    /**
     * 合并上下文信息
     */
    private Object mergeContexts(UserContext userContext, ConversationContext conversationContext) {
        try {
            return contextManager.mergeContexts(userContext, conversationContext);
        } catch (Exception e) {
            logger.warn("Error merging contexts, using default merge strategy", e);
            
            // 默认合并策略
            Map<String, Object> merged = new HashMap<>();
            
            if (userContext != null) {
                merged.put("user", userContext);
                merged.put("userId", userContext.getUserId());
                merged.put("userPreferences", userContext.getPreferences());
                merged.put("userProfile", userContext.getProfile());
            }
            
            if (conversationContext != null) {
                merged.put("conversation", conversationContext);
                merged.put("sessionId", conversationContext.getSessionId());
                merged.put("conversationHistory", conversationContext.getConversationHistory());
                merged.put("currentTopic", conversationContext.getCurrentTopic());
                merged.put("sessionVariables", conversationContext.getSessionVariables());
            }
            
            merged.put("mergeTimestamp", LocalDateTime.now());
            merged.put("mergeStrategy", "default");
            
            return merged;
        }
    }
    
    /**
     * 更新上下文缓存状态
     */
    private void updateContextCacheStatus(ProcessingContext context, 
                                        UserContext userContext, 
                                        ConversationContext conversationContext) {
        Map<String, Object> cacheStatus = new HashMap<>();
        
        // 用户上下文缓存状态
        if (userContext != null) {
            cacheStatus.put("userContextCached", true);
            cacheStatus.put("userUpdateTime", userContext.getUpdateTime());
            cacheStatus.put("userLastActiveTime", userContext.getUpdateTime());
            cacheStatus.put("userPreferencesExists", userContext.getPreferences() != null);
        } else {
            cacheStatus.put("userContextCached", false);
        }
        
        // 对话上下文缓存状态
        if (conversationContext != null) {
            cacheStatus.put("conversationContextCached", true);
            cacheStatus.put("conversationStartTime", conversationContext.getStartTime());
            cacheStatus.put("conversationLastActiveTime", conversationContext.getLastActiveTime());
            cacheStatus.put("conversationHistorySize", 
                    conversationContext.getConversationHistory() != null ? 
                            conversationContext.getConversationHistory().size() : 0);
        } else {
            cacheStatus.put("conversationContextCached", false);
        }
        
        context.setProcessingData("contextCacheStatus", cacheStatus);
    }
    
    /**
     * 刷新上下文缓存
     */
    public void refreshContextCache(ProcessingContext context) {
        logger.debug("Refreshing context cache for requestId: {}", context.getRequestId());
        
        try {
            // 清除当前上下文
            context.setUserContext(null);
            context.setConversationContext(null);
            context.removeProcessingData("mergedContext");
            context.removeProcessingData("contextCacheStatus");
            
            // 重新加载上下文
            doProcess(context);
            
        } catch (Exception e) {
            logger.error("Error refreshing context cache for requestId: {}", context.getRequestId(), e);
        }
    }
    
    /**
     * 更新用户上下文
     */
    public void updateUserContext(ProcessingContext context, UserContext updatedUserContext) {
        try {
            if (updatedUserContext != null && context.getUserId() != null) {
                // 更新上下文管理器中的用户上下文
                contextManager.updateUserContext(context.getUserId(), updatedUserContext);
                
                // 更新处理上下文中的用户上下文
                context.setUserContext(updatedUserContext);
                
                // 重新合并上下文
                Object mergedContext = mergeContexts(updatedUserContext, context.getConversationContext());
                context.setProcessingData("mergedContext", mergedContext);
                
                logger.debug("User context updated for userId: {}", context.getUserId());
            }
        } catch (Exception e) {
            logger.error("Error updating user context for userId: {}", context.getUserId(), e);
        }
    }
    
    /**
     * 更新对话上下文
     */
    public void updateConversationContext(ProcessingContext context, ConversationContext updatedConversationContext) {
        try {
            if (updatedConversationContext != null && context.getSessionId() != null) {
                // 更新上下文管理器中的对话上下文
                contextManager.updateConversationContext(context.getSessionId(), updatedConversationContext);
                
                // 更新处理上下文中的对话上下文
                context.setConversationContext(updatedConversationContext);
                
                // 重新合并上下文
                Object mergedContext = mergeContexts(context.getUserContext(), updatedConversationContext);
                context.setProcessingData("mergedContext", mergedContext);
                
                logger.debug("Conversation context updated for sessionId: {}", context.getSessionId());
            }
        } catch (Exception e) {
            logger.error("Error updating conversation context for sessionId: {}", context.getSessionId(), e);
        }
    }
    
    @Override
    protected void preProcess(ProcessingContext context) {
        super.preProcess(context);
        context.updateState("LOADING_CONTEXT");
    }
    
    @Override
    protected void postProcess(ProcessingContext context, ProcessingResult result) {
        super.postProcess(context, result);
        if (result.isSuccess()) {
            context.updateState("CONTEXT_LOADED");
        } else {
            context.updateState("CONTEXT_LOAD_FAILED");
        }
    }
    
    @Override
    public boolean supports(ProcessingContext context) {
        // 上下文处理器支持所有已验证的请求
        return context != null && 
               context.getOriginalRequest() != null &&
               context.getUserId() != null &&
               context.getSessionId() != null;
    }
    
    @Override
    protected ProcessingResult handleError(ProcessingContext context, Exception exception) {
        // 上下文加载失败时，创建默认上下文继续处理
        logger.warn("Context loading failed, creating default contexts for requestId: {}", 
                context.getRequestId(), exception);
        
        logger.debug("handleError called with exception: {}", exception.getMessage());
        
        try {
            // 创建默认上下文
            UserContext defaultUserContext = createDefaultUserContext(context.getUserId());
            ConversationContext defaultConversationContext = createDefaultConversationContext(context.getSessionId());
            
            context.setUserContext(defaultUserContext);
            context.setConversationContext(defaultConversationContext);
            
            // 记录使用了默认上下文
            context.setProcessingData("contextStatus", "DEFAULT");
            context.setProcessingData("contextError", exception.getMessage());
            
            logger.debug("Default contexts created successfully, returning success=true");
            
            return ProcessingResult.builder()
                    .success(true) // 虽然加载失败，但使用默认上下文继续处理
                    .shouldContinue(true)
                    .processorName(PROCESSOR_NAME)
                    .resultData("contextStatus", "DEFAULT")
                    .resultData("contextError", exception.getMessage())
                    .build();
                    
        } catch (Exception e) {
            logger.error("Failed to create default contexts for requestId: {}", context.getRequestId(), e);
            return super.handleError(context, e);
        }
    }
}